//<<<+++OPENSOURCE
//<<<+++OPENSOURCE_LICENSE
//<<<+++OPENSOURCE_BEGIN LIC==FOXIT||LIC==GOOGLE

//<<<+++OPENSOURCE_MUST_BEGIN
#ifndef _FX_UNICODE_
#define _FX_UNICODE_
//<<<+++OPENSOURCE_MUST_END

#ifndef _FXM_OPENSOURCE_
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT

//Classes defined in this header
class IFX_CharProperties;
class CFX_Char;

//<<<+++OPENSOURCE_MUST_END
#endif

//*****************************************************************************
//* Character break properties
//*****************************************************************************
enum FX_CHARBREAKPROP
{
	FX_CBP_OP = 0,			// Open Punctuation	(XA)
	FX_CBP_CL = 1,			// Close Punctuation	(XB)
	FX_CBP_QU = 2,			// Quotaton	(XB/XA)
	FX_CBP_GL = 3,			// Non-breaking	(XB/XA)
	FX_CBP_NS = 4,			// Nonstarter	(XB)
	FX_CBP_EX = 5,			// Exclamation/Interrogation	(XB)
	FX_CBP_SY = 6,			// Symbols Allowing Break After	(A)
	FX_CBP_IS = 7,			// Infix Numeric Separator	(XB)
	FX_CBP_PR = 8,			// Prefix Numberic	(XA)
	FX_CBP_PO = 9,			// Postfix Numberic	(XB)
	FX_CBP_NU = 10,			// Numberic	(XP)
	FX_CBP_AL = 11,			// Alphabetic	(XP)			
	FX_CBP_ID = 12,			// Ideographic	(B/A)
	FX_CBP_IN = 13,			// Inseparable	(XP)
	FX_CBP_HY = 14,			// Hyphen	(XA)
	FX_CBP_BA = 15,			// Break After	(A)
	FX_CBP_BB = 16,			// Break Before	(B)
	FX_CBP_B2 = 17,			// Break Opportunity Before and After	(B/A/XP)
	FX_CBP_ZW = 18,			// Zero Width Space	(A)
	FX_CBP_CM = 19,			// Combining Mark	(XB)
	FX_CBP_WJ = 20,			// Word Joiner	(XB/XA)
	FX_CBP_H2 = 21,			// Hangul LV Syllable	(B/A)
	FX_CBP_H3 = 22,			// Hangul LVT Syllable	(B/A)
	FX_CBP_JL = 23,			// Hangul L Jamo	(B)
	FX_CBP_JV = 24,			// Hangul V Jamo	(XA/XB)
	FX_CBP_JT = 25,			// Hangul T Jamo	(A)
	
	//Resolved outside the pair table
	FX_CBP_BK = 26,			// Mandatory Break	(A)								
	FX_CBP_CR = 27,			// Carriage Return	(A)
	FX_CBP_LF = 28,			// Line Feed	(A)
	FX_CBP_NL = 29,			// Next Line	(A)
	FX_CBP_SA = 30,			// Complex Contex Dependent	(P)
	FX_CBP_SG = 31,			// Surrogate	(XP)
	FX_CBP_CB = 32,			// Contingent Break Opportunity	(B/A)
	FX_CBP_XX = 33,			// Unknown	(XP)
	FX_CBP_AI = 34,			// Ambiguous
	FX_CBP_SP = 35,			// Space	(A)
	FX_CBP_TB = 37,			// tab

	FX_CBP_NONE = 36,		// None break
};

//*****************************************************************************
//* Bidi classes
//*****************************************************************************
#define FX_BIDICLASSBITS		6							//number of bits for bidi classes
#define FX_BIDICLASSBITSMASK	(31 << FX_BIDICLASSBITS)	//mask value for bidi classes
//Enumeration for bidi classes
enum FX_BIDICLASS
{
	// input types
	// ON MUST be zero, code relies on ON = N = 0
	FX_BIDICLASS_ON		= 0,	// Other Neutral
	FX_BIDICLASS_L		= 1,	// Left Letter
	FX_BIDICLASS_R		= 2,	// Right Letter
	FX_BIDICLASS_AN		= 3, 	// Arabic Number
	FX_BIDICLASS_EN		= 4, 	// European Number
	FX_BIDICLASS_AL		= 5, 	// Arabic Letter (Right-to-left)
	FX_BIDICLASS_NSM	= 6,	// Non-spacing Mark
	FX_BIDICLASS_CS		= 7, 	// Common Separator
	FX_BIDICLASS_ES		= 8, 	// European Separator
	FX_BIDICLASS_ET		= 9, 	// European Terminator (post/prefix e.g. $ and %)

	// resolved types
	FX_BIDICLASS_BN		= 10, 	// Boundary neutral (type of RLE etc after explicit levels)

	// input types,
	FX_BIDICLASS_S		= 11,	// Segment Separator (TAB)		// used only in L1
	FX_BIDICLASS_WS		= 12, 	// White space					// used only in L1
	FX_BIDICLASS_B		= 13,	// Paragraph Separator (aka as PS)

	// types for explicit controls
	// these are used only in X1-X9
	FX_BIDICLASS_RLO	= 14,
	FX_BIDICLASS_RLE	= 15,
	FX_BIDICLASS_LRO	= 16,
	FX_BIDICLASS_LRE	= 17,
	FX_BIDICLASS_PDF	= 18,

	// resolved types, also resolved directions
	FX_BIDICLASS_N		= FX_BIDICLASS_ON,  // alias, where ON, WS and S are treated the same
};

//*****************************************************************************
//* Character types
//*****************************************************************************
#define FX_CHARTYPEBITS		11
#define FX_CHARTYPEBITSMASK	(15 << FX_CHARTYPEBITS)
enum FX_CHARTYPE
{
	FX_CHARTYPE_Unknown				= 0,						//unknown character type
	FX_CHARTYPE_Tab					= (1 << FX_CHARTYPEBITS),	//tab character, '\t'
	FX_CHARTYPE_Space				= (2 << FX_CHARTYPEBITS),	//space character, ' '
	FX_CHARTYPE_Control				= (3 << FX_CHARTYPEBITS),	//control character
	FX_CHARTYPE_Combination			= (4 << FX_CHARTYPEBITS),	//combination character
	FX_CHARTYPE_Numeric				= (5 << FX_CHARTYPEBITS),	//numeric character, '0' - '9'
	FX_CHARTYPE_Normal				= (6 << FX_CHARTYPEBITS),	//normal character

	FX_CHARTYPE_ArabicAlef			= (7 << FX_CHARTYPEBITS),  //arabic alef character
	FX_CHARTYPE_ArabicSpecial		= (8 << FX_CHARTYPEBITS),  //arabic special character
	FX_CHARTYPE_ArabicDistortion	= (9 << FX_CHARTYPEBITS),	//arabic distortion character
	FX_CHARTYPE_ArabicNormal		= (10 << FX_CHARTYPEBITS),	//arabic normal character
	FX_CHARTYPE_ArabicForm			= (11 << FX_CHARTYPEBITS), //arabic form character
	FX_CHARTYPE_Arabic				= (12 << FX_CHARTYPEBITS),	//arabic character, internal usage
};

//*****************************************************************************
//* Character properties
//*****************************************************************************
typedef struct _FX_CHARPROPERTIES
{
	union
	{
		struct
		{
			FX_DWORD	dwBreakType		: 6;	//6bits, break types
			FX_DWORD	dwBidiClass		: 5;	//5bits, bidi classes
			FX_DWORD	dwCharType		: 4;	//4bits, character types
			FX_DWORD	dwRotation		: 1;	//1bit, rotation flag
			FX_DWORD	dwCJKSpecial	: 1;	//1bit, special punctuations for CJK vertical layout
			FX_DWORD	dwVertIndex		: 6;	//6bits, vertical mirror index
			FX_DWORD	dwBidiIndex		: 9;	//9bits, bidi mirror index
		};
		FX_DWORD	dwCharProps;
	};
}FX_CHARPROPERTIES;

//Retrieve unicode properties list
FX_DWORD FX_GetUnicodeProperties(FX_WCHAR wch);
//Determin whether a character is a control code or not
//Control code contains '\t', '\n', '\v', '\f', '\r', 0x200D, 0x2028, 0x2029, 0xFEFF, 0xFFFE, 0xFFFF
FX_BOOL	FX_IsCtrlCode(FX_WCHAR ch);
//Determin whether a character need rotate in vertical layout
FX_BOOL	FX_IsRotationCode(FX_WCHAR ch);
FX_BOOL FX_IsCombinationChar(FX_WCHAR wch);
FX_BOOL	FX_IsBidiChar(FX_WCHAR wch);
//Retrieve mirror code
FX_WCHAR FX_GetMirrorChar(FX_WCHAR wch, FX_BOOL bRTL, FX_BOOL bVertical);
FX_WCHAR FX_GetMirrorChar(FX_WCHAR wch, FX_DWORD dwProps, FX_BOOL bRTL, FX_BOOL bVertical);

#ifndef _FXM_OPENSOURCE_
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT

class IFX_CharProperties
{
public:
	static IFX_CharProperties*		Create();

	//Release the current object
	virtual void					Release() = 0;

	//Retrieve line break type
	virtual FX_CHARBREAKPROP		GetLineBreakType(FX_WCHAR wch) const = 0;
	//Retrieve bidi class
	virtual FX_BIDICLASS			GetBidiClass(FX_WCHAR wch) const = 0;
	//Retrieve character type
	virtual FX_DWORD				GetCharType(FX_WCHAR wch) const = 0;
	//Retrieve the rotation status in vertical layout
	virtual FX_BOOL					IsRotationChar(FX_WCHAR wch) const = 0;
	//Retrieve whether a character is CJK special punctuation in vertical layout
	virtual FX_BOOL					IsCJKSpecial(FX_WCHAR wch) const = 0;
	//Determine whether need mirror character in vertical layout
	virtual FX_BOOL					HasVerticalMirror(FX_WCHAR wch) const = 0;
	//Retrieve the vertical mirror character code
	virtual FX_WCHAR				GetVerticalMirror(FX_WCHAR wch) const = 0;
	//Determine whether need mirror character in bidi layout
	virtual FX_BOOL					HasBidiMirror(FX_WCHAR wch) const = 0;
	//Retrieve the bidi mirror character code
	virtual FX_WCHAR				GetBidiMirror(FX_WCHAR wch) const = 0;
};

//*****************************************************************************
//* Character
//*****************************************************************************
class CFX_Char : public CFX_Object
{
public:
	CFX_Char() : m_wCharCode(0)
				, m_nBreakType(0)
				, m_nRotation(0)
				, m_dwCharProps(0)
				, m_dwCharStyles(0)
				, m_iCharWidth(0)
				, m_iHorizontalScale(100)
				, m_iVertialScale(100)
	{
	}
	CFX_Char(FX_WORD wCharCode, FX_DWORD dwCharProps)
				: m_wCharCode(wCharCode)
				, m_nBreakType(0)
				, m_nRotation(0)
				, m_dwCharProps(dwCharProps)
				, m_dwCharStyles(0)
				, m_iCharWidth(0)
				, m_iHorizontalScale(100)
				, m_iVertialScale(100)
	{
	}

	FX_DWORD	GetCharType() const {return m_dwCharProps & FX_CHARTYPEBITSMASK;}

	FX_WORD		m_wCharCode;	//character code, 0xFEFF for unknown character or special purpose
	FX_BYTE		m_nBreakType;	//break type
	FX_INT8		m_nRotation;	//character rotation
	FX_DWORD	m_dwCharProps;	//character properties
	FX_DWORD	m_dwCharStyles;	//character styles
	FX_INT32	m_iCharWidth;	//character width
	FX_INT32	m_iHorizontalScale;	//character horizontal scale, in percentage
	FX_INT32	m_iVertialScale;	//character vertical scale, in percentage
};
typedef CFX_ArrayTemplate<CFX_Char>	CFX_CharArray;

//*****************************************************************************
//* Text character
//*****************************************************************************
class CFX_TxtChar : public CFX_Char
{
public:
	CFX_TxtChar() : CFX_Char()
				   , m_dwStatus(0)
				   , m_iBidiClass(0)
				   , m_iBidiLevel(0)
				   , m_iBidiPos(0)
				   , m_iBidiOrder(0)
				   , m_pUserData(NULL)
	{
	}

	FX_DWORD			m_dwStatus;		//character status
	FX_INT16			m_iBidiClass;	//bidi class
	FX_INT16			m_iBidiLevel;	//bidi level
	FX_INT16			m_iBidiPos;		//bidi position
	FX_INT16			m_iBidiOrder;	//bidi order
	FX_LPVOID			m_pUserData;	//user data
};
typedef CFX_ArrayTemplate<CFX_TxtChar>	CFX_TxtCharArray;

//*****************************************************************************
//* RTF character
//*****************************************************************************
class CFX_RTFChar : public CFX_Char
{
public:
	CFX_RTFChar() : CFX_Char()
				   , m_dwStatus(0)
				   , m_iFontSize(0)
				   , m_iFontHeight(0)
				   , m_iBidiClass(0)
				   , m_iBidiLevel(0)
				   , m_iBidiPos(0)
				   , m_dwLayoutStyles(0)
				   , m_dwIdentity(0)
				   , m_pUserData(NULL)
	{
	}

	FX_DWORD			m_dwStatus;			//character status
	FX_INT32			m_iFontSize;		//font size
	FX_INT32			m_iFontHeight;		//font height
	FX_INT16			m_iBidiClass;		//bidi class
	FX_INT16			m_iBidiLevel;		//bidi level
	FX_INT16			m_iBidiPos;			//bidi position
	FX_INT16			m_iBidiOrder;		//bidi order
	FX_DWORD			m_dwLayoutStyles;	//layout styles
	FX_DWORD			m_dwIdentity;		//identity code
	IFX_Unknown			*m_pUserData;		//user data
};
typedef CFX_ArrayTemplate<CFX_RTFChar>	CFX_RTFCharArray;

//*****************************************************************************
//* Unicode Casing Mapping
//*****************************************************************************
#define FX_CASEMAP_TYPE_L 0		// To Lower case
#define FX_CASEMAP_TYPE_U 1		// To Upper case
#define FX_CASEMAP_TYPE_T 2		// To Title	case
#define FX_CASEMAP_TYPE_F 3		// To Fold	case

/**
* Get a casing of unicode.
*
* @param[in] type			Casing type refer to  FX_CASEMAP_TYPE_XXX
* @param[in] wsSrc			Source string.
* @param[in] pDest			Dest string.
* @param[in] nDestLength	The length of dest.
* @param[in] bFull			Is simple map or full map.
* @param[out] pMapIndex		The dest character map to the index of source string.
* @return The length of string mapped.
*/
FX_INT32 FX_ToCase(FX_INT32 type, FX_WSTR wsSrc, FX_LPWSTR pDest, FX_INT32 nDestLength, FX_BOOL bFull = FALSE, CFX_Int32Array* pMapIndex = NULL);

//<<<+++OPENSOURCE_MUST_END
#endif

//<<<+++OPENSOURCE_MUST_BEGIN
#endif //_FX_UNICODE_
//<<<+++OPENSOURCE_MUST_END

//<<<+++OPENSOURCE_END
